import * as BABYLON from 'babylonjs'
import {SkyMaterial} from "babylonjs-materials";
import { addLabelToMesh } from './CreateGUI';


/**
 * Babylon.js测试案例类
 */
class Playground {






    /**
     * 渲染
     * @param engine
     * @param scene
     * @constructor
     */
    private static  DoRender(engine:BABYLON.Engine,scene:BABYLON.Scene):void{
        //渲染
        engine.runRenderLoop(()=>{
            if(scene&&scene.activeCamera)
            {
                scene.render();
            }
        });

        window.addEventListener("resize",()=>{
            engine.resize();
        });
    }

    /**
     * 创建一个球
     * @param canvas
     * @constructor
     */
    public  static  CreateSphereScene(canvas:HTMLCanvasElement):BABYLON.Scene{

        //创建引擎
        let engine=new BABYLON.Engine(canvas,true);
        //创建场景
        let scene=new BABYLON.Scene(engine);
        //创建相机
        let camera=new BABYLON.FreeCamera("camera1",new BABYLON.Vector3(0,5,-10),scene);
        camera.setTarget(BABYLON.Vector3.Zero());
        camera.attachControl(canvas,true);
        //创建灯光
        let light=new BABYLON.HemisphericLight("light1",new BABYLON.Vector3(0,1,0),scene);
        light.intensity=0.7;
        //创建小球
        let sphere=BABYLON.Mesh.CreateSphere("sphere1",16,2,scene);
        sphere.position.y=1;
        //增加标签
        addLabelToMesh(sphere);
        //创建地板
        let ground=BABYLON.Mesh.CreateGround("ground1",6,6,2,scene);
        const groundMat = new BABYLON.StandardMaterial("groundMat",scene);
        groundMat.diffuseColor = new BABYLON.Color3(0, 1, 0);
        ground.material = groundMat; //Place the material property of the ground
        Playground.DoRender(engine,scene);
        return  scene;
    }


    public  static  CreateCube(canvas:HTMLCanvasElement)
    {
        const engine=new BABYLON.Engine(canvas,true);
        const scene=new BABYLON.Scene(engine);
        const camera=new BABYLON.ArcRotateCamera("camera",-Math.PI/2,Math.PI/2.5,3,new BABYLON.Vector3(0,0,0),scene);
        camera.attachControl(canvas,true);
        const light=new BABYLON.HemisphericLight("light",new BABYLON.Vector3(0,1,0),scene);
        const box=BABYLON.MeshBuilder.CreateBox("box",{width:0.5,height:0.5,depth:0.5});
        Playground.DoRender(engine,scene);
    }


    public static  TestImportMeshAsync(canvas:HTMLCanvasElement)
    {
        const engine=new BABYLON.Engine(canvas,true,{preserveDrawingBuffer: true, stencil: true});
        const scene=new BABYLON.Scene(engine);

        let skyMaterial=new SkyMaterial("skyMaterial",scene);
        skyMaterial.backFaceCulling = false;

        const camera = new BABYLON.ArcRotateCamera("camera", -Math.PI / 2, Math.PI / 2.5, 15, new BABYLON.Vector3(0, 0, 0),scene);
        camera.attachControl(canvas, true);
        const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(1, 1, 0),scene);
        // BABYLON.SceneLoader.ImportMeshAsync("semi_house", "https://assets.babylonjs.com/meshes/", "both_houses_scene.babylon",scene);
        // BABYLON.SceneLoader.ImportMeshAsync(["ground", "semi_house"], "https://assets.babylonjs.com/meshes/", "both_houses_scene.babylon");
        BABYLON.SceneLoader.ImportMeshAsync("", "https://assets.babylonjs.com/meshes/", "both_houses_scene.babylon").then((result) => {
            const house1 = scene.getMeshByName("detached_house");
            house1.position.y = 2;
            const house2 = result.meshes[2];
            house2.position.y = 1;
        });
        Playground.DoRender(engine,scene);
    }


    public  static  CreateVillage(canvas:HTMLCanvasElement)
    {
        const engine=new BABYLON.Engine(canvas,true);
        const scene=new BABYLON.Scene(engine);
        const camera=new BABYLON.ArcRotateCamera("camera",-Math.PI/2,Math.PI/2.5,3,new BABYLON.Vector3(0,0,0),scene);
        camera.attachControl(canvas,true);
        const light=new BABYLON.HemisphericLight("light",new BABYLON.Vector3(0,1,0),scene);

         //顶
        const roof = BABYLON.MeshBuilder.CreateCylinder("roof", {diameter: 1.3, height: 1.2, tessellation: 3});
        roof.scaling.x = 0.75;
        roof.scaling.y = 2;
        roof.rotation.z = Math.PI / 2;
        roof.position.y = 1.22;
        const roofMat=new BABYLON.StandardMaterial("roofMat",scene);
        roofMat.diffuseTexture=new BABYLON.Texture("https://assets.babylonjs.com/environments/roof.jpg",scene);
        roof.material=roofMat;

        //box
        const boxMat=new BABYLON.StandardMaterial("boxMat",scene);
        // boxMat.diffuseTexture=new BABYLON.Texture("https://www.babylonjs-playground.com/textures/floor.png",scene);
        boxMat.diffuseTexture = new BABYLON.Texture("https://assets.babylonjs.com/environments/cubehouse.png",scene);

        const faceUV = [];
        faceUV[0] = new BABYLON.Vector4(0.6, 0.0, 1.0, 1.0); //rear face
        faceUV[1] = new BABYLON.Vector4(0.0, 0.0, 0.4, 1.0); //front face
        faceUV[2] = new BABYLON.Vector4(0.4, 0, 0.6, 1.0); //right side
        faceUV[3] = new BABYLON.Vector4(0.4, 0, 0.6, 1.0); //left side
        const box=BABYLON.MeshBuilder.CreateBox("box",{width: 2, faceUV:faceUV,wrap:true});
        // box.scaling=new BABYLON.Vector3(2,1.5,3);
        box.position.y = 0.5;
        // box.rotation.y = Math.PI / 4;//旋转使用弧度
        // box.rotation.y = BABYLON.Tools.ToRadians(45);//也可以用角度
        box.material=boxMat;

        //合并网格
        const house = BABYLON.Mesh.MergeMeshes([box, roof], true, false, null, false, true);

        //克隆房子
        // let clonedHouse = house.clone("clonedHouse");
        let clonedHouse = house.createInstance("instanceHouse")
        clonedHouse.position=new BABYLON.Vector3(3,0,0);

        //地板
        const ground=BABYLON.MeshBuilder.CreateGround("ground",{width:10,height:10},scene);
        const groundMat=new BABYLON.StandardMaterial("groundMat",scene);
        groundMat.diffuseColor=new BABYLON.Color3(0,1,0);
        ground.material=groundMat;



        //播放音乐
        const music = new BABYLON.Sound("music", "../../static/buru.mp3", scene,null, { loop: false, autoplay: true });

        Playground.DoRender(engine,scene);
    }

    public  static  CreateSmallCar(canvas:HTMLCanvasElement){
        const engine=new BABYLON.Engine(canvas,true);
        const scene=new BABYLON.Scene(engine);
        const camera=new BABYLON.ArcRotateCamera("camera",-Math.PI/2,Math.PI/2.5,3,new BABYLON.Vector3(0,0,0),scene);
        camera.attachControl(canvas,true);
        const light=new BABYLON.HemisphericLight("light",new BABYLON.Vector3(0,1,0),scene);

        //通过代码创建小车
        function CreateCarByCode() {
            //小车
            //base
            const outline = [
                new BABYLON.Vector3(-0.3, 0, -0.1),
                new BABYLON.Vector3(0.2, 0, -0.1),
            ]
            //curved front
            for (let i = 0; i < 20; i++) {
                outline.push(new BABYLON.Vector3(0.2 * Math.cos(i * Math.PI / 40), 0, 0.2 * Math.sin(i * Math.PI / 40) - 0.1));
            }
            //top
            outline.push(new BABYLON.Vector3(0, 0, 0.1));
            outline.push(new BABYLON.Vector3(-0.3, 0, 0.1));

            //face UVs
            const faceUV = [];
            faceUV[0] = new BABYLON.Vector4(0, 0.5, 0.38, 1);
            faceUV[1] = new BABYLON.Vector4(0, 0, 1, 0.5);
            faceUV[2] = new BABYLON.Vector4(0.38, 1, 0, 0.5);
            const carMat = new BABYLON.StandardMaterial("carMat", scene);
            carMat.diffuseTexture = new BABYLON.Texture("https://assets.babylonjs.com/environments/car.png", scene);
            const car = BABYLON.MeshBuilder.ExtrudePolygon("car", {
                shape: outline,
                depth: 0.2,
                faceUV: faceUV,
                wrap: true
            });
            car.material = carMat;


            //wheel face UVs
            const wheelUV = [];
            wheelUV[0] = new BABYLON.Vector4(0, 0, 1, 1);
            wheelUV[1] = new BABYLON.Vector4(0, 0.5, 0, 0.5);
            wheelUV[2] = new BABYLON.Vector4(0, 0, 1, 1);
            //car material
            const wheelMat = new BABYLON.StandardMaterial("wheelMat", scene);
            wheelMat.diffuseTexture = new BABYLON.Texture("https://assets.babylonjs.com/environments/wheel.png", scene);
            const wheelRB = BABYLON.MeshBuilder.CreateCylinder("wheelRB", {
                diameter: 0.125,
                height: 0.05,
                faceUV: wheelUV
            })
            wheelRB.material = wheelMat;
            wheelRB.parent = car;
            wheelRB.position.z = -0.1;
            wheelRB.position.x = -0.2;
            wheelRB.position.y = 0.035;

            const wheelRF = wheelRB.clone("wheelRF");
            wheelRF.position.x = 0.1;

            const wheelLB = wheelRB.clone("wheelLB");
            wheelLB.position.y = -0.2 - 0.035;

            const wheelLF = wheelRF.clone("wheelLF");
            wheelLF.position.y = -0.2 - 0.035;


            //Animate the Wheels
            const animWheel = new BABYLON.Animation("wheelAnimation", "rotation.y", 30, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);
            const wheelKeys = [];
            //At the animation key 0, the value of rotation.y is 0
            wheelKeys.push({
                frame: 0,
                value: 0
            });
            //At the animation key 30, (after 1 sec since animation fps = 30) the value of rotation.y is 2PI for a complete rotation
            wheelKeys.push({
                frame: 30,
                value: 2 * Math.PI
            });
            //set the keys
            animWheel.setKeys(wheelKeys);
            //Link this animation to a wheel
            wheelRB.animations = [];
            wheelRB.animations.push(animWheel);
            wheelRF.animations = [];
            wheelRF.animations.push(animWheel);
            wheelLB.animations = [];
            wheelLB.animations.push(animWheel);
            wheelLF.animations = [];
            wheelLF.animations.push(animWheel);
            scene.beginAnimation(wheelRB, 0, 30, true);
            scene.beginAnimation(wheelRF, 0, 30, true);
            scene.beginAnimation(wheelLB, 0, 30, true);
            scene.beginAnimation(wheelLF, 0, 30, true);
        }
        // CreateCarByCode();

        //通过文件加载小车动画
        BABYLON.SceneLoader.ImportMeshAsync("","../../static/","car.babylon").then(()=>{
            const wheelRB = scene.getMeshByName("wheelRB");
            const wheelRF = scene.getMeshByName("wheelRF");
            const wheelLB = scene.getMeshByName("wheelLB");
            const wheelLF = scene.getMeshByName("wheelLF");
            console.log(wheelRB.animations)
            scene.beginAnimation(wheelRB, 0, 30, true);
            scene.beginAnimation(wheelRF, 0, 30, true);
            scene.beginAnimation(wheelLB, 0, 30, true);
            scene.beginAnimation(wheelLF, 0, 30, true);
        });


        // 测试人物动画
        // BABYLON.SceneLoader.ImportMeshAsync("him", "https://playground.babylonjs.com/scenes/Dude/", "Dude.babylon", scene).then((result) => {
        //     var dude = result.meshes[0];
        //     dude.scaling = new BABYLON.Vector3(0.25, 0.25, 0.25);
        //     scene.beginAnimation(result.skeletons[0], 0, 100, true, 1.0);
        // });

        Playground.DoRender(engine,scene);
    }


    public  static  CreateDistantHills(canvas:HTMLCanvasElement):BABYLON.Scene{

        //创建引擎
        let engine=new BABYLON.Engine(canvas,true);
        //创建场景
        let scene=new BABYLON.Scene(engine);
        //创建相机
        let camera=new BABYLON.FreeCamera("camera1",new BABYLON.Vector3(0,5,-10),scene);
        camera.setTarget(BABYLON.Vector3.Zero());
        camera.attachControl(canvas,true);
        //创建灯光
        let light=new BABYLON.HemisphericLight("light1",new BABYLON.Vector3(0,1,0),scene);
        light.intensity=0.7;

        Playground.DoRender(engine,scene);
        return  scene;
    }

}
export default  Playground;
